/*******************************************************************************
*  file    : rpcserver.cpp
*  created : 18.08.2013
*  author  : 
*******************************************************************************/

#include "rpcserver.hpp"

#include <QCoreApplication>
#include <QVariant>
#include <qtxmlrpc.h>
#include <qlogger.hpp>

#include "modemmanager.hpp"
#include "archivedb.hpp"

namespace
{
QLogger* l = QLoggerEngine::getLogger("core");
}

RpcServer::RpcServer(QObject *parent) :
    QObject(parent)
{
    connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(stop())  );
}

RpcServer::RpcServer(const QString& address, quint16 port, QObject* parent) :
    QObject(parent)
{
    address_ = address;
    port_    = port;
    connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(stop())  );
}

RpcServer::~RpcServer()
{

}

bool RpcServer::isListening()
{
    if( srv_.isNull() )
        return false;

    return srv_->isListening();
}

void RpcServer::start()
{
    if( isListening() )
        {
            stop();
        }
    srv_.reset(new XmlRpcServer);
    initServer();
    if(srv_->listen(QHostAddress(address_), port_))
        logInfo(l)<<QString("Rpc server listening on %1:%2")
                           .arg(srv_->serverAddress().toString())
                           .arg(srv_->serverPort());
    else
        logError(l)<<QString("Can't start server. %1")
                     .arg(srv_->errorString());

}

void RpcServer::stop()
{
    srv_.reset();
    logInfo(l)<<"RPC server stoped.";
}

void RpcServer::initServer()
{
    if(srv_)
        {
            srv_->registerSlot( this       , SLOT(modemStatus     () ) );
            srv_->registerSlot( this       , SLOT(getMoleList     () ) );
            srv_->registerSlot( srv_.data(), SLOT(echo            (QVariant)) );
            srv_->registerSlot( this       , SLOT(addMole         (QVariant)) );
            srv_->registerSlot( this       , SLOT(updateMole      (QVariant)) );
            srv_->registerSlot( this       , SLOT(sendInfoRequest (QVariant)) );
            srv_->registerSlot( this       , SLOT(sendPosRequest  (QVariant)) );
            srv_->registerSlot( this       , SLOT(getLastInfo     (QVariant)) );
            srv_->registerSlot( this       , SLOT(getWorkedTasks  (QVariant)) );
            srv_->registerSlot( this       , SLOT(hideMoles       (QVariant)) );
            srv_->registerSlot( this       , SLOT(addSmsToOutgoing(QVariant,QVariant)) );
            srv_->registerSlot( this       , SLOT(sendModeRequest (QVariant,QVariant)) );
        }
}

quint16 RpcServer::port() const
{
    return port_;
}

void RpcServer::setPort(const quint16& port)
{
    port_ = port;
}

QString RpcServer::address() const
{
    return address_;
}

void RpcServer::setAddress(const QString& address)
{
    address_ = address;
}

QVariant RpcServer::modemStatus()
{
    QVariant res;
    res = ModemManager::instance()->modemStatus();
    return res;
}

QVariant RpcServer::addMole(const QVariant& v)
{
    if( v.type() == QVariant::List )
        {
            QVariantList list = v.toList();
            if(list.size()>4)
                {
                    return ArchiveDB::instance()->addMole(list[0].toString(),
                                                          list[1].toString(),
                                                          list[2].toString(),
                                                          list[3].toString(),
                                                          list[4].toString()
                                                          );
                }
            else
                return createFault(1, tr("Не удалось создать запись маяка.") );
        }
    return createFault(1, tr("Не удалось создать запись маяка.") );
}

QVariant RpcServer::updateMole(const QVariant &v)
{
    if( v.type() == QVariant::List )
        {
            QVariantList list = v.toList();
            if(list.size()>5)
                {
                    return ArchiveDB::instance()->updateMole(list[0].toString(),
                                                             list[1].toString(),
                                                             list[2].toString(),
                                                             list[3].toString(),
                                                             list[4].toString(),
                                                             list[5].toInt()
                                                             );
                }
            else
                return createFault(1, tr("Не удалось создать запись маяка.") );
        }
    return createFault(1, tr("Не удалось создать запись маяка.") );
}

QVariant RpcServer::getMoleList()
{
    QVariantList res;

    for(const MoleLine& line : ArchiveDB::instance()->getMoles() )
        {
            QVariantList l;
            for(const QString& f : line) l << f;
            res << QVariant(l);
        }

    return QVariant(res);
}

QVariant RpcServer::hideMoles(const QVariant &num_idx)
{
    return ArchiveDB::instance()->hideMoles(num_idx.toStringList());
}

QVariant RpcServer::addSmsToOutgoing(const QVariant& num_idx, const QVariant& txt)
{
    return ArchiveDB::instance()->addSmsToOutgoing(num_idx.toInt(), txt.toString());
}

QVariant RpcServer::sendInfoRequest(const QVariant &num_idx)
{
    return ModemManager::instance()->sendInfoRequest(num_idx.toStringList());
}

QVariant RpcServer::sendPosRequest(const QVariant &num_idx)
{
    return ModemManager::instance()->sendPosRequest(num_idx.toStringList());
}

QVariant RpcServer::sendModeRequest(const QVariant &num_idx, const QVariant &mode)
{
    return ModemManager::instance()->sendModeRequest(num_idx.toStringList(), mode.toInt());
}

QVariant RpcServer::getLastInfo(const QVariant &num_idx)
{
    QVariantList res;
    std::vector<IncomingLine> incom =
            ArchiveDB::instance()->getLastIncomingListWithText(num_idx.toStringList(),
                                                               QStringLiteral("Krot"));
    for( const IncomingLine& line : incom)
        {
            QVariantList lst;
            for( const QString& item : line)
                lst << QString(item).replace(QChar(0x0d),QChar(';'));
            res << QVariant(lst);
        }

    incom =
            ArchiveDB::instance()->getLastIncomingListWithText(num_idx.toStringList(),
                                                               QStringLiteral("maps.google"));
    for( const IncomingLine& line : incom)
        {
            QVariantList lst;
            for( const QString& item : line)
                lst << QString(item).remove(QChar(0x0d));
            res << QVariant(lst);
        }

    return QVariant(res);
}

QVariant RpcServer::getWorkedTasks(const QVariant& num_idx)
{    
    if( num_idx.toList().size() )
        {
            const MoleTaskList& task_list = ModemManager::instance()->taskList();
            QVariantList res_list;
            for( const std::unique_ptr<MoleTask>& mt : task_list)
                {
                    QVariantList line;
                    line << mt->id()     << mt->requestNum() << mt->requestText()
                         << mt->ansver() << mt->startTime().toString("yyyy-MM-dd hh:mm:ss")  << mt->status();
                    res_list << QVariant(line);
                }
            return QVariant(res_list);
        }
    return QVariant();
}

